package com.pay.ioopos.worker;

import static androidx.work.BackoffPolicy.LINEAR;
import static androidx.work.WorkRequest.MIN_BACKOFF_MILLIS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

import android.content.Context;

import androidx.work.Constraints;
import androidx.work.Data;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.ExistingWorkPolicy;
import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;

import com.pay.ioopos.App;
import com.pay.ioopos.support.scan.weixin.MyWxPayFace;

import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * @author mo_yq5
 * @since 2021-07-15
 */
public abstract class WorkerFacory {
    private static final Constraints constraints = new Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build();

    private static Context context;

    public static void beginWorkers(Context context) {
        WorkerFacory.context = context;
        enqueveTimeBarUpdateOneTime();
        enqueveAppBindOneTime();
        enqueveAppCheckInPeriodic();
        enqueveAppPantPeriodic();
        enqueveAppKeepAliveOneTime();
        enqueveWxOfflineIniPeriodic();
        enqueveWxOnlineIniPeriodic();
    }

    public static void cancelWorkers() {
        if (null != context) {
            WorkManager.getInstance(context).cancelAllWork();
            return;
        }
        WorkManager.getInstance(App.getInstance()).cancelAllWork();
    }

    public static void enquevePayRepealOneTime(String cusOrderNo) {

        Data data = new Data.Builder()
                .putString("cusOrderNo", cusOrderNo)
                .build();

        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(PayRepealWorker.class)
                .setInputData(data)
                .setConstraints(constraints);

        WorkManager.getInstance(context).enqueue(builder.build());
    }

    public static void enquevePayUploadOneTime() {

        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(PayUploadWorker.class)
                .setConstraints(constraints);

        WorkManager.getInstance(context).enqueue(builder.build());
    }

    public static void enqueveCardLockReportOneTime(String cardNo, String cardUid) {

        Data data = new Data.Builder()
                .putString("cardNo", cardNo)
                .putString("cardUid", cardUid)
                .build();

        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(CardLockReportWorker.class)
                .setInputData(data)
                .setConstraints(constraints);

        WorkManager.getInstance(context).enqueue(builder.build());
    }

    public static void enqueveCardBlackLoadOneTime() {

        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(CardBlackLoadWorker.class)
                .setConstraints(constraints);

        WorkManager.getInstance(context).enqueue(builder.build());
    }

    public static void enqueveWxBlackLoadOneTime() {

        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(WxBlackLoadWorker.class)
                .setConstraints(constraints);

        WorkManager.getInstance(context).enqueue(builder.build());
    }

    public static void enqueveWxReportIniOneTime(Context context, boolean force) {
        Data data = new Data.Builder()
                .putBoolean(WxReportIniWorker.PARAM_FORCE, force)
                .build();

        OneTimeWorkRequest.Builder buildler = new OneTimeWorkRequest
                .Builder(WxReportIniWorker.class)
                .setInputData(data)
                .setConstraints(constraints);

        WorkManager.getInstance(context).enqueue(buildler.build());
    }

    public static void enqueveWxReportIniOneTime(boolean force) {
        enqueveWxReportIniOneTime(context, force);
    }

    public static void enqueveWxReportExeOneTime(Map<String, Object> map) {
        Data data = new Data.Builder()
                .putAll(map)
                .build();

        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest
                .Builder(WxReportExeWorder.class)
                .setInputData(data)
                .setConstraints(constraints);

        WorkManager.getInstance(context).enqueue(builder.build());
    }

    public static void enqueveWxUserLoadOneTime() {
        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest
                .Builder(WxUserLoadWorker.class)
                .setConstraints(constraints);

        WorkManager.getInstance(context).enqueue(builder.build());
    }

    public static void enqueveWxOfflineIniPeriodic() {
        if (!App.DEV_IS_FACE || !MyWxPayFace.IS_OFFLINE) {
            return;
        }
        PeriodicWorkRequest.Builder builder = new PeriodicWorkRequest
                .Builder(WxOfflineIniWorker.class, 30, TimeUnit.MINUTES)
                .setConstraints(constraints);

        WorkManager.getInstance(context)
                .enqueueUniquePeriodicWork(WxOfflineIniWorker.class.getSimpleName(),
                        ExistingPeriodicWorkPolicy.REPLACE,
                        builder.build());
    }

    public static void enqueveWxOfflineIniOneTime(boolean reset) {
        if (!App.DEV_IS_FACE || !MyWxPayFace.IS_OFFLINE) {
            return;
        }
        Data data = new Data.Builder()
                .putBoolean("reset", reset)
                .build();

        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest
                .Builder(WxOfflineIniWorker.class)
                .setInputData(data)
                .setConstraints(constraints);

        WorkManager.getInstance(context).enqueue(builder.build());
    }

    public static void enqueveWxOnlineIniPeriodic() {
        if (!App.DEV_IS_FACE || MyWxPayFace.IS_OFFLINE) {
            return;
        }
        PeriodicWorkRequest.Builder builder = new PeriodicWorkRequest
                .Builder(WxOnlineIniWorker.class, 30, TimeUnit.MINUTES)
                .setConstraints(constraints);

        WorkManager.getInstance(context)
                .enqueueUniquePeriodicWork(WxOnlineIniWorker.class.getSimpleName(),
                        ExistingPeriodicWorkPolicy.REPLACE,
                        builder.build());
    }

    public static void enqueveWxOnlineIniOneTime(boolean reset) {
        if (!App.DEV_IS_FACE || MyWxPayFace.IS_OFFLINE) {
            return;
        }
        Data data = new Data.Builder()
                .putBoolean("reset", reset)
                .build();

        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest
                .Builder(WxOnlineIniWorker.class)
                .setInputData(data)
                .setConstraints(constraints);

        WorkManager.getInstance(context).enqueue(builder.build());
    }

    public static void enqueveAppCheckInPeriodic() {
        PeriodicWorkRequest.Builder builder = new PeriodicWorkRequest
                .Builder(AppCheckInWorker.class, 24, TimeUnit.HOURS)
                .setConstraints(constraints)
                .setBackoffCriteria(LINEAR, MIN_BACKOFF_MILLIS, MILLISECONDS);

        WorkManager.getInstance(context)
                .enqueueUniquePeriodicWork(AppCheckInWorker.class.getSimpleName(),
                        ExistingPeriodicWorkPolicy.REPLACE,
                        builder.build());
    }

    public static void enqueveAppPantOneTime(boolean force, boolean online) {
        Data data = new Data.Builder()
                .putBoolean(AppPantWorker.PARAM_FORCE, force)
                .putBoolean(AppPantWorker.PARAM_ONLINE, online)
                .build();

        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest
                .Builder(AppPantWorker.class)
                .setInputData(data)
                .setConstraints(constraints);

        WorkManager.getInstance(context).enqueue(builder.build());
    }

    public static void enqueveAppPantPeriodic() {
        Data data = new Data.Builder()
                .putBoolean(AppPantWorker.PARAM_ONLINE, true)
                .build();

        PeriodicWorkRequest.Builder builder = new PeriodicWorkRequest
                .Builder(AppPantWorker.class, 1, TimeUnit.HOURS)
                .setInitialDelay(10, TimeUnit.SECONDS)
                .setInputData(data)
                .setConstraints(constraints);

        WorkManager.getInstance(context)
                .enqueueUniquePeriodicWork(AppPantWorker.class.getSimpleName(),
                        ExistingPeriodicWorkPolicy.REPLACE,
                        builder.build());
    }

    public static void enqueveSslCertLoadOneTime(boolean force) {
        Data data = new Data.Builder()
                .putBoolean(SslCertLoadWorker.PARAM_FORCE, force)
                .build();

        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest
                .Builder(SslCertLoadWorker.class)
                .setInputData(data)
                .setConstraints(constraints);

        WorkManager.getInstance(context).enqueue(builder.build());
    }

    public static void enqueveSslCertLoadOneTime() {
        enqueveSslCertLoadOneTime(false);
    }

    public static void enqueveAppBindOneTime() {
        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest
                .Builder(AppBindWorker.class)
                .setConstraints(constraints)
                .setBackoffCriteria(LINEAR, MIN_BACKOFF_MILLIS, MILLISECONDS);

        WorkManager.getInstance(context).enqueue(builder.build());
    }

    public static void enqueveTimeBarUpdateOneTime() {

        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest
                .Builder(TimeBarUpdateWorker.class);

        WorkManager.getInstance(context)
                .enqueueUniqueWork(TimeBarUpdateWorker.class.getSimpleName(),
                        ExistingWorkPolicy.REPLACE,
                        builder.build());
    }

    public static void enqueveAppKeepAliveOneTime() {

        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest
                .Builder(AppKeepAliveWorker.class);

        WorkManager.getInstance(context)
                .enqueueUniqueWork(AppKeepAliveWorker.class.getSimpleName(),
                        ExistingWorkPolicy.REPLACE,
                        builder.build());
    }

}
